package com.joplus.housekeeper.ui.view;

import android.content.Context;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

/**
 * Created by bianxiang on 16/4/22.
 */
public class DragLayout extends FrameLayout {
    private boolean isShowShadow = true;
    private GestureDetectorCompat gestureDetector;
    private ViewDragHelper dragHelper;
    private DragListener dragListener;
    private int range;
    private int width;
    private int height;
    private int mainLeft;
    private Context context;
    private ImageView iv_shadow;
    private LinearLayout vg_left;
    private RelativeLayout vg_main;
    private Status status = Status.Close;
    private Boolean isDragable = true;


    private float defshowTouchStartX = 100;//默认可以拉开的起始位置
    private float startTouchRawX;//开始点击RawX
    private float moveTouchRaws;//滑动是的RawX
    private float endTouchRawX;//结束触摸的RawX

    private float startTouchRawY;//开始点击的RawX
    Boolean isIntercept = false;//为假则拦截事件

    public DragLayout(Context context) {
        this(context, null);
    }

    public DragLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        this.context = context;
    }

    public DragLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        gestureDetector = new GestureDetectorCompat(context, new YScrollDetector());
        dragHelper = ViewDragHelper.create(this, dragHelperCallback);
    }


    /**
     * 设置是否可以拉开侧边栏
     *
     * @param able
     */
    public void setDragAble(Boolean able) {
        isDragable = able;
    }


    class YScrollDetector extends GestureDetector.SimpleOnGestureListener {
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float dx, float dy) {
            return Math.abs(dy) <= Math.abs(dx);
        }

        @Override
        public boolean onSingleTapUp(MotionEvent e) {

            close();

            return super.onSingleTapUp(e);
        }
    }

    private ViewDragHelper.Callback dragHelperCallback = new ViewDragHelper.Callback() {

        @Override
        public int clampViewPositionHorizontal(View child, int left, int dx) {
            if (mainLeft + dx < 0) {
                return 0;
            } else if (mainLeft + dx > range) {
                return range;
            } else {
                return left;
            }
        }

        @Override
        public boolean tryCaptureView(View child, int pointerId) {

            if (isDragable) {
                return true;
            } else {
                return false;
            }


        }

        @Override
        public int getViewHorizontalDragRange(View child) {
            return width;
        }

        @Override
        public void onViewReleased(View releasedChild, float xvel, float yvel) {
            super.onViewReleased(releasedChild, xvel, yvel);
            if (xvel > 0) {
                open();
            } else if (xvel < 0) {
                close();
            } else if (releasedChild == vg_main && mainLeft > range * 0.3) {
                open();
            } else if (releasedChild == vg_left && mainLeft > range * 0.7) {
                open();
            } else {
                close();
            }
        }

        @Override
        public void onViewPositionChanged(View changedView, int left, int top,
                                          int dx, int dy) {
            if (changedView == vg_main) {
                mainLeft = left;
            } else {
                mainLeft = mainLeft + left;
            }
            if (mainLeft < 0) {
                mainLeft = 0;
            } else if (mainLeft > range) {
                mainLeft = range;
            }

            if (isShowShadow) {
                iv_shadow.layout(mainLeft, 0, mainLeft + width, height);
            }
            if (changedView == vg_left) {
                vg_left.layout(0, 0, width, height);
                vg_main.layout(mainLeft, 0, mainLeft + width, height);
            }

            dispatchDragEvent(mainLeft);
        }
    };

    public interface DragListener {
        public void onOpen();

        public void onClose();

        public void onDrag(float percent);
    }

    public void setDragListener(DragListener dragListener) {
        this.dragListener = dragListener;
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        if (isShowShadow) {
            iv_shadow = new ImageView(context);
//            iv_shadow.setImageResource(R.drawable.shadow);
            LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
            addView(iv_shadow, 1, lp);
        }
        vg_left = (LinearLayout) getChildAt(0);
        vg_main = (RelativeLayout) getChildAt(isShowShadow ? 2 : 1);
//        vg_left.setPadding();
//        vg_main.setDragLayout(this);
        vg_left.setClickable(true);
        vg_main.setClickable(true);
    }

    public ViewGroup getVg_main() {
        return vg_main;
    }

    public ViewGroup getVg_left() {
        return vg_left;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = vg_left.getMeasuredWidth();
        height = vg_left.getMeasuredHeight();
        range = (int) (width * 0.75f);
        vg_left.setPadding(0, 0, width - range, 0);

    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        vg_left.layout(0, 0, width, height);
        vg_main.layout(mainLeft, 0, mainLeft + width, height);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {


        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:

                if (status == Status.Open && ev.getX() > range) {
                    close();
                }


                startTouchRawX = ev.getRawX();//开始按下的X位置
                startTouchRawY = ev.getRawY();//开始按下的Y
                isIntercept = false;//按下的时候先选择不拦截事件

                if (startTouchRawX < defshowTouchStartX) {//只要在默认边界外就可以了
                    isIntercept = true;//从左边临界内部开始滑动才拦截事件
                } else if (startTouchRawX > defshowTouchStartX) {
                    switch (getStatus()) {
                        case Open://侧滑打开状态下，用原来的处理


                            break;
                        case Close:
                            return false;//从左边临界外部开始直接不拦截事件

                    }

                }
                if (startTouchRawX > defshowTouchStartX && startTouchRawY > height * 4 / 5) {//超出边界外且在高度的4/5以下不拦截事件
                    isIntercept = false;//这是为了处理和表情冲突产生的
                }


                break;
            case MotionEvent.ACTION_MOVE:

                moveTouchRaws = ev.getRawX();

                if (startTouchRawX < defshowTouchStartX) {//从默认拉开位置外侧开始，说明是拉开操作
                    if (moveTouchRaws > startTouchRawX) {//滑动位置>开始点击
                        isIntercept = true;
                    } else {

                    }


                } else {//从默认拉开位置外侧开始，这里只能是关闭操作
                    if (moveTouchRaws < startTouchRawX) {//滑动位置<开始点击
                        isIntercept = true;
                    } else {

                    }
                }
                break;


            case MotionEvent.ACTION_UP:

                endTouchRawX = ev.getRawX();
                //开始点击的位置>默认的边界
                if (startTouchRawX < defshowTouchStartX) {
                    if (endTouchRawX > startTouchRawX) {//右滑
                        isIntercept = true;
                    }
                } else {
                    isIntercept = false;
                }

                break;
        }

        if (isIntercept) {

            try {
                return dragHelper.shouldInterceptTouchEvent(ev) && gestureDetector.onTouchEvent(ev);
            } catch (Exception e) {
                return false;
            }

        } else {
            return isIntercept;
        }



    }

    @Override
    public boolean onTouchEvent(MotionEvent e) {
        try {
            dragHelper.processTouchEvent(e);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return false;
    }

    private void dispatchDragEvent(int mainLeft) {
        if (dragListener == null) {
            return;
        }
        float percent = mainLeft / (float) range;

        dragListener.onDrag(percent);
        Status lastStatus = status;
        if (lastStatus != getStatus() && status == Status.Close) {
            dragListener.onClose();

        } else if (lastStatus != getStatus() && status == Status.Open) {
            dragListener.onOpen();

        }
    }



    @Override
    public void computeScroll() {
        if (dragHelper.continueSettling(true)) {
            ViewCompat.postInvalidateOnAnimation(this);
        }
    }

    public enum Status {
        Drag, Open, Close
    }

    public Status getStatus() {
        if (mainLeft == 0) {
            status = Status.Close;
        } else if (mainLeft == range) {
            status = Status.Open;
        } else {
            status = Status.Drag;
        }
        return status;
    }

    public void open() {
        open(true);
    }

    public void open(boolean animate) {
        if (animate) {
            if (dragHelper.smoothSlideViewTo(vg_main, range, 0)) {
                ViewCompat.postInvalidateOnAnimation(this);
            }
        } else {
            vg_main.layout(range, 0, range * 2, height);
            dispatchDragEvent(range);
        }
    }

    public void close() {
        close(true);
    }

    public void close(boolean animate) {

        if (animate) {
            if (dragHelper.smoothSlideViewTo(vg_main, 0, 0)) {
                ViewCompat.postInvalidateOnAnimation(this);
            }
        } else {
            vg_main.layout(0, 0, width, height);
            dispatchDragEvent(0);
        }
    }

}